var Application = (function () {
    let remoteName = 'applicationCso';
    let emptyHandlerArray = [];
    let handlers = new Map();

    /**
     * 初始化
     */
    async function InitializeAsync() {
        await window.TimerComponent.WaitUntilAsync(() => window.CefSharp != undefined && window.sessionStorage.getItem("Initialized")==='True');
    }

    /**
     * 加载C#端绑定对象
     * @param name 绑定对象类名(首字母小写)
     */
    async function LoadRemoteBindingObjectAsync(name) {
        if (window.CefSharp == undefined) {
            window.Logger.LogWarning(`远端执行器(${remoteName})获取失败(CefSharp未声明)`);
            return false;
        }

        if (!window.CefSharp.IsObjectCached(name)) {
            const response = await window.CefSharp.BindObjectAsync(remoteName);
            if (!response.Success) {
                window.Logger.LogWarning(`远端执行器(${remoteName})加载失败(${response.Message})`);
                return false;
            }
        }
        return true;
    }

    /**
     * 注册C#端消息处理器
     * @param opcode 消息码
     * @param handler 处理器
     */
    function Register(opcode, handler) {
        if (!handlers.has(opcode)) {
            handlers.set(opcode, new Array());
        }

        handlers.get(opcode).push(handler);
    }

    /**
     * 通知C#端处理消息
     * @param opcode 消息码
     * @param message 消息体
     */
    function PostMessage(opcode, message) {
        if (window.CefSharp == undefined) {
            window.Logger.LogWarning(`远端执行器(${remoteName})获取失败(CefSharp未声明)`);
        } else {
            window.CefSharp.PostMessage({ Opcode: opcode, Message: message });
        }
    }

    /**
     * 通知C#端处理请求并等待返回
     * @param opcode 消息码
     * @param message 消息体
     * @returns 响应消息
     */
    async function PostMessageAsync(opcode, message) {
        return new Promise(resolve => window.CefSharp.PostMessage({
            Opcode: opcode, Message: message, Callback: resolve
        }));
    }

    /**
     * C#端执行消息
     * @param opcode 消息码
     * @param message 消息体
     */
    function RunMessage(opcode, message) {
        if (!handlers.has(opcode)) {
            window.Logger.LogWarning(`消息码(${opcode})未注册处理器`);
        } else {
            for (const handler of handlers.get(opcode)) {
                try {
                    handler(message);
                } catch (error) {
                    window.Logger.LogError(`消息码(${opcode})处理失败,(${error})`);
                }
            }
        }
    }

    /**
     * 加载并反序列化SessionStorage数据
     * @param key 键
     * @param interval 刷新间隔
     * @param timeout 超时时间
     */
    async function LoadSessionStorageAsync(key, interval, timeout) {
        let content = null;
        await window.TimerComponent.WaitUntilAsync(() => (content = window.sessionStorage.getItem(key)) != null, interval, timeout);
        try {
            return JSON.parse(content);
        } catch (error) {
            window.Logger.LogError(`加载SessionStorage失败,(${error})`);
            return null;
        }
    }

    function modifyWindow() {
        window.shutdown = function () {
            window.Application.PostMessage(Opcode.ShutdownMessage, {});
        };

        window.minimizedAsync = async function () {
            const response = await window.Application.PostMessageAsync(Opcode.MinimizedRequest, {});
            window.Logger.LogInformation(`最小化(${JSON.stringify(response)})`);
        };
    }

    modifyWindow();

    return {
        InitializeAsync,
        LoadRemoteBindingObjectAsync,
        Register,
        PostMessage,
        PostMessageAsync,
        RunMessage,
        LoadSessionStorageAsync,
    };
})();